package main

import (
	"fmt"
	"math/rand"
	"time"
)

const (
	width  = 15
	height = 5
)

type Universe [][]bool

func (u Universe) Show() {
	for i := range u {
		for j := range u[i] {
			if u[i][j] {
				fmt.Printf("+")
			} else {
				fmt.Printf("-")
			}
		}
		fmt.Printf("\n")
	}
}

func (u Universe) Seed() {
	rand.Seed(time.Now().UnixNano())
	for i := 0; i < len(u); i++ {
		for j := 0; j < len(u[i])/4+1; j++ {
			num := rand.Intn(len(u[i]))
			u[i][num] = true
		}
	}
}

func (u Universe) Alive(x, y int) bool {
	if (x >= height || y >= width) || (x < 0 || y < 0) {
		return u[(x+height)%height][(y+width)%width]
	} else {
		return u[x][y]
	}
}

func (u Universe) Neighbors(x, y int) int {
	direction := [][]int{{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}
	count := 0

	for i := 0; i < len(direction); i++ {
		if u.Alive(x+direction[i][0], y+direction[i][1]) {
			count++
		}
	}
	return count
}

func (u Universe) Next(x, y int) bool {
	neighborCount := u.Neighbors(x, y)
	// fmt.Println(neighborCount)
	if neighborCount < 2 {
		return false
	}
	if (neighborCount == 2 || neighborCount == 3) && u.Alive(x, y) {
		return true
	}
	if neighborCount == 3 && !u.Alive(x, y) {
		return true
	}
	// 大于3个邻居
	return false
}

func NewUniverse() Universe {
	newUn := make(Universe, height)
	for i := range newUn {
		newUn[i] = make([]bool, width)
	}

	return newUn
}

func Step(a, b Universe) {
	for i := 0; i < 3; i++ {
		for i := range a {
			for j := range a[i] {
				b[i][j] = a.Next(i, j)
			}
		}
		a, b = b, a
		fmt.Printf("\x0c")
		a.Show()
	}
}

func main() {
	newU := NewUniverse()
	newCopy := NewUniverse()
	newU.Seed()
	newU.Show()

	Step(newU, newCopy)
	// time.Sleep(4000)
	// fmt.Printf("\x0c")
}
